/*===============================================
Copyright (c): Technology Co.,Ltd. ALL rights reserved. 
                                                                 
  Create by: Lin
      Email:
       Date:
   Filename:
Description:
    Version:
Last Change:
                                                                 
=======================================*/
                                                                 
`ifndef MAC_MONITOR_SV
`define MAC_MONITOR_SV

`include "mac_seq_item.sv"

class mac_monitor extends uvm_monitor;
	`uvm_component_utils(mac_monitor)
	virtual interface mii_if vif;
	int port_num;
	uvm_analysis_port #(mac_seq_item) analysis_port;
	
	extern function new(string name, uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void connect_phase(uvm_phase phase);
	extern task main_phase(uvm_phase phase);
	extern task do_i_mon(mac_seq_item trans, int port_num);
	extern task do_o_mon(mac_seq_item trans, int port_num);


endclass

function mac_monitor::new(string name, uvm_component parent);
	super.new(name, parent);
	analysis_port = new("analysis_port", this);
endfunction

function void mac_monitor::build_phase(uvm_phase phase);
	super.build_phase(phase);
endfunction

function void mac_monitor::connect_phase(uvm_phase phase);
	super.connect_phase(phase);
	if (!uvm_config_db #(virtual mii_if #(PORT_NUM))::get(this, "", "vif", vif))
		`uvm_error("NOVIF", {"virtual interface must be set for: ", get_full_name, "vif"})
	if (!uvm_config_db #(int)::get(this, "", "port_num", port_num))
		`uvm_error("CON_DB_ERR", {"port num must be set for: ", get_full_name, "port_num"})
endfunction

task mac_monitor::main_phase(uvm_phase phase);
	mac_seq_item m_trans;
	`uvm_info(get_type_name(), "main_phase", UVM_HIGH)
	@(vif.rst_n);
	fork
		while(1) begin
			@(posedge vif.mon_clk.mii_rx_dv[port_num])
			m_trans = mac_seq_item::type_id::create("mtrans");
			do_o_mon(m_trans, port_num);
			`uvm_info(get_type_name(), "rx receive trans", UVM_HIGH)
			//$display("\n\033[36m*****************************************");
			//m_trans.print();
			//$display("\033[36m*****************************************\033[0m\n");
			analysis_port.write(m_trans);
		end
		while(1) begin
			@(posedge vif.mon_clk.mii_tx_en[port_num])
			m_trans = mac_seq_item::type_id::create("mtrans");
			do_i_mon(m_trans, port_num);
			`uvm_info(get_type_name(), "tx receive trans", UVM_HIGH)
			//	m_trans.print();
			analysis_port.write(m_trans);
		end
	join
endtask

task mac_monitor::do_o_mon(mac_seq_item trans, int port_num);
	byte unsigned data_q[$];
	byte unsigned recv_temp;

	trans.port_num = port_num;
	trans.output_time = $time;	
	while (vif.mon_clk.mii_rx_dv[port_num] != 0) begin
		@(vif.mon_clk)
		recv_temp[3:0] = vif.mon_clk.mii_rx_data[port_num]; 
		@(vif.mon_clk)
		recv_temp[7:4] = vif.mon_clk.mii_rx_data[port_num];
		data_q.push_back(recv_temp);
		@(posedge vif.mii_rx_clk);
	end
	trans.do_unpack_bytes(data_q);

endtask

task mac_monitor::do_i_mon(mac_seq_item trans, int port_num);
	byte unsigned data_q[$];
	byte unsigned recv_temp;

	trans.port_num = port_num;
	trans.input_time = $time;	
	while (vif.mon_clk.mii_tx_en[port_num] != 0) begin
		@(vif.mon_clk)
		recv_temp[3:0] = vif.mon_clk.mii_tx_data[port_num]; 
		@(vif.mon_clk)
		recv_temp[7:4] = vif.mon_clk.mii_tx_data[port_num];
		data_q.push_back(recv_temp);
	//	`uvm_info("DATA_TEST", $sformatf("data_q[%d] is %h", i, data_q[i]), UVM_HIGH);	

		@(posedge vif.mii_tx_clk);
	end
	trans.do_unpack_bytes(data_q);

endtask

`endif
